Defer the generated event to the mainloop and don't generate one at all if
authorRichard Hult <richard@imendio.com>
Mon, 31 Mar 2008 13:15:15 +0000 (13:15 +0000)
committerRichard Hult <rhult@src.gnome.org>
Mon, 31 Mar 2008 13:15:15 +0000 (13:15 +0000)
2008-03-28  Richard Hult  <richard@imendio.com>

* gdk/quartz/gdkevents-quartz.c: (gdk_event_translate),
(_gdk_quartz_events_trigger_crossing_events): Defer the generated
event to the mainloop and don't generate one at all if the
toplevel didn't change. Use the actual window and not the toplevel
as event window. These changes make the generated crossing events
match the X11 behavior and fixes issues with e.g. tooltips,
comboboxes and menus.

* gdk/quartz/GdkQuartzView.c: Don't update the tracking rect if
the view has no window, it will be updated as soon as it's put
inside a window.

* gdk/quartz/gdkwindow-quartz.c:
(_gdk_quartz_window_debug_highlight): Make it possible to track
multiple windows with debug highlighting.
(show_window_internal): Remove workaround for tooltips and popups
that is no longer needed with the above changes.

svn path=/trunk/; revision=19951

ChangeLog
gdk/quartz/GdkQuartzView.c
gdk/quartz/gdkevents-quartz.c
gdk/quartz/gdkprivate-quartz.h
gdk/quartz/gdkwindow-quartz.c

index bb6dabd02a7e1bd64b709fb73380ea8c3d30a782..f5c7b5ad4e75c39cef4bf8db301d9109f044765a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2008-03-28  Richard Hult  <richard@imendio.com>
+
+       * gdk/quartz/gdkevents-quartz.c: (gdk_event_translate),
+       (_gdk_quartz_events_trigger_crossing_events): Defer the generated
+       event to the mainloop and don't generate one at all if the
+       toplevel didn't change. Use the actual window and not the toplevel
+       as event window. These changes make the generated crossing events
+       match the X11 behavior and fixes issues with e.g. tooltips,
+       comboboxes and menus.
+
+       * gdk/quartz/GdkQuartzView.c: Don't update the tracking rect if
+       the view has no window, it will be updated as soon as it's put
+       inside a window.
+
+       * gdk/quartz/gdkwindow-quartz.c:
+       (_gdk_quartz_window_debug_highlight): Make it possible to track
+       multiple windows with debug highlighting.
+       (show_window_internal): Remove workaround for tooltips and popups
+       that is no longer needed with the above changes.
+
 2008-03-26  Federico Mena Quintero  <federico@novell.com>
 
        * gtk/gtkfilechooserentry.c (commit_completion_and_refresh): New
index 1063e7bfb94f3476334b2d50ffa10e743f27a60d..843df50e4791cd58e55648cb72540d03c9b30cc4 100644 (file)
 -(void)setFrame:(NSRect)frame
 {
   [super setFrame:frame];
-  [self updateTrackingRect];
+
+  if ([self window])
+    [self updateTrackingRect];
 }
 
 @end
index dc7701b6fd14ff94fa8dbd4538375e56e884e270..912fdec898e8565cd5ce10387e814d516224428c 100644 (file)
@@ -888,7 +888,7 @@ _gdk_quartz_events_update_mouse_window (GdkWindow *window)
 
 #ifdef G_ENABLE_DEBUG
   if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
-    _gdk_quartz_window_debug_highlight (window);
+    _gdk_quartz_window_debug_highlight (window, 0);
 #endif /* G_ENABLE_DEBUG */  
 
   if (window)
@@ -1092,18 +1092,34 @@ find_mouse_window_for_ns_event (NSEvent *nsevent,
  * window.
  */
 void
-_gdk_quartz_events_trigger_crossing_events (void)
+_gdk_quartz_events_trigger_crossing_events (gboolean defer_to_mainloop)
 {
   NSPoint point;
-  gint x; 
-  gint y;
+  gint x, y
+  gint x_toplevel, y_toplevel;
   GdkWindow *mouse_window;
+  GdkWindow *toplevel;
   GdkWindowImplQuartz *impl;
   guint flags = 0;
   NSTimeInterval timestamp = 0;
   NSEvent *current_event;
   NSEvent *nsevent;
 
+  if (defer_to_mainloop)
+    {
+      nsevent = [NSEvent otherEventWithType:NSApplicationDefined
+                                   location:NSZeroPoint
+                              modifierFlags:0
+                                  timestamp:0
+                               windowNumber:0
+                                    context:nil
+                                    subtype:GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
+                                      data1:0
+                                      data2:0];
+      [NSApp postEvent:nsevent atStart:NO];
+      return;
+    }
+
   point = [NSEvent mouseLocation];
   x = point.x;
   y = _gdk_quartz_window_get_inverted_screen_y (point.y);
@@ -1112,16 +1128,24 @@ _gdk_quartz_events_trigger_crossing_events (void)
   if (!mouse_window || mouse_window == _gdk_root)
     return;
 
-  /* NSMouseEntered always happens on the toplevel. */
-  mouse_window = gdk_window_get_toplevel (mouse_window);
+  toplevel = gdk_window_get_toplevel (mouse_window);
+
+  /* We ignore crossing within the same toplevel since that is already
+   * handled elsewhere.
+   */
+  if (toplevel == gdk_window_get_toplevel (current_mouse_window))
+    return;
+
+  get_converted_window_coordinates (_gdk_root,
+                                    x, y,
+                                    toplevel,
+                                    &x_toplevel, &y_toplevel);
 
   get_converted_window_coordinates (_gdk_root,
                                     x, y,
                                     mouse_window,
                                     &x, &y);
 
-  impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (mouse_window)->impl);
-
   /* Fix up the event to be less fake if possible. */
   current_event = [NSApp currentEvent];
   if (current_event)
@@ -1130,8 +1154,12 @@ _gdk_quartz_events_trigger_crossing_events (void)
       timestamp = [current_event timestamp];
     }
 
+  if (timestamp == 0)
+    timestamp = GetCurrentEventTime ();
+
+  impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
   nsevent = [NSEvent otherEventWithType:NSApplicationDefined
-                               location:NSMakePoint(x, impl->height - y)
+                               location:NSMakePoint (x_toplevel, impl->height - y_toplevel)
                           modifierFlags:flags
                               timestamp:timestamp
                            windowNumber:[impl->toplevel windowNumber]
@@ -1141,7 +1169,7 @@ _gdk_quartz_events_trigger_crossing_events (void)
                                   data2:0];
 
 #ifdef G_ENABLE_DEBUG
-  /*_gdk_quartz_window_debug_highlight (mouse_window);*/
+  /*_gdk_quartz_window_debug_highlight (mouse_window, 0);*/
 #endif
 
   synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
@@ -1702,6 +1730,14 @@ gdk_event_translate (NSEvent *nsevent)
         }
     }
 
+  /* Handle our generated "fake" crossing events. */
+  if ([nsevent type] == NSApplicationDefined && 
+      [nsevent subtype] == GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING)
+    {
+      _gdk_quartz_events_trigger_crossing_events (FALSE);
+      return TRUE;
+    }
+
   /* Keep track of button state, since we don't get that information
    * for key events. 
    */
index 39696ec11d59d1b5ef9ea4dda73bb5b8c6ec327f..859a802b886c9e14c2a6cad588bc52d2f9851c9a 100644 (file)
@@ -144,7 +144,8 @@ void       _gdk_quartz_window_attach_to_parent      (GdkWindow *window);
 void       _gdk_quartz_window_detach_from_parent    (GdkWindow *window);
 void       _gdk_quartz_window_did_become_main       (GdkWindow *window);
 void       _gdk_quartz_window_did_resign_main       (GdkWindow *window);
-void       _gdk_quartz_window_debug_highlight       (GdkWindow *window);
+void       _gdk_quartz_window_debug_highlight       (GdkWindow *window,
+                                                     gint       number);
 
 /* Events */
 typedef enum {
@@ -159,7 +160,7 @@ void         _gdk_quartz_events_update_mouse_window    (GdkWindow *window);
 void         _gdk_quartz_events_update_cursor          (GdkWindow *window);
 void         _gdk_quartz_events_send_map_events        (GdkWindow *window);
 GdkEventMask _gdk_quartz_events_get_current_event_mask (void);
-void         _gdk_quartz_events_trigger_crossing_events(void);
+void         _gdk_quartz_events_trigger_crossing_events(gboolean   defer_to_mainloop);
 
 extern GdkWindow *_gdk_quartz_keyboard_grab_window;
 extern GdkWindow *_gdk_quartz_pointer_grab_window;
index ddf2e81cdcb1920707e85c6e42b8f3aa40fe64d8..997e90db6cf50d0f19c68c5fadc4f786aa508a99 100644 (file)
@@ -538,22 +538,31 @@ get_ancestor_coordinates_from_child (GdkWindow *child_window,
 }
 
 void
-_gdk_quartz_window_debug_highlight (GdkWindow *window)
+_gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
 {
   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
   gint x, y;
   GdkWindow *toplevel;
   gint tx, ty;
-  static NSWindow *debug_window;
-  static NSRect old_rect;
+  static NSWindow *debug_window[10];
+  static NSRect old_rect[10];
   NSRect rect;
+  NSColor *color;
+
+  g_return_if_fail (number >= 0 && number <= 9);
 
   if (window == _gdk_root)
     return;
 
   if (window == NULL)
-    return;
+    {
+      if (debug_window[number])
+        [debug_window[number] close];
+      debug_window[number] = NULL;
+
+      return;
+    }
 
   toplevel = gdk_window_get_toplevel (window);
   get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y);
@@ -562,37 +571,56 @@ _gdk_quartz_window_debug_highlight (GdkWindow *window)
   x += tx;
   y += ty;
 
-  rect =  NSMakeRect (x,
-                      _gdk_quartz_window_get_inverted_screen_y (y + impl->height),
-                      impl->width, impl->height);
+  rect = NSMakeRect (x,
+                     _gdk_quartz_window_get_inverted_screen_y (y + impl->height),
+                     impl->width, impl->height);
 
-  if (debug_window &&
-      rect.origin.x == old_rect.origin.x &&
-      rect.origin.y == old_rect.origin.y &&
-      rect.size.width == old_rect.size.width &&
-      rect.size.height == old_rect.size.height)
-    {
-      return;
-    }
+  if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
+    return;
+
+  old_rect[number] = rect;
 
-  old_rect = rect;
+  if (debug_window[number])
+    [debug_window[number] close];
 
-  if (debug_window)
-    [debug_window close];
+  debug_window[number] = [[NSWindow alloc] initWithContentRect:rect
+                                                     styleMask:NSBorderlessWindowMask
+                                                      backing:NSBackingStoreBuffered
+                                                        defer:NO];
 
-  debug_window = [[NSWindow alloc] initWithContentRect:rect
-                                             styleMask:NSBorderlessWindowMask
-                                              backing:NSBackingStoreBuffered
-                                                defer:NO];
+  switch (number)
+    {
+    case 0:
+      color = [NSColor redColor];
+      break;
+    case 1:
+      color = [NSColor blueColor];
+      break;
+    case 2:
+      color = [NSColor greenColor];
+      break;
+    case 3:
+      color = [NSColor yellowColor];
+      break;
+    case 4:
+      color = [NSColor brownColor];
+      break;
+    case 5:
+      color = [NSColor purpleColor];
+      break;
+    default:
+      color = [NSColor blackColor];
+      break;
+    }
 
-  [debug_window setBackgroundColor:[NSColor redColor]];
-  [debug_window setAlphaValue:0.4];
-  [debug_window setOpaque:NO];
-  [debug_window setReleasedWhenClosed:YES];
-  [debug_window setIgnoresMouseEvents:YES];
-  [debug_window setLevel:NSFloatingWindowLevel];
+  [debug_window[number] setBackgroundColor:color];
+  [debug_window[number] setAlphaValue:0.4];
+  [debug_window[number] setOpaque:NO];
+  [debug_window[number] setReleasedWhenClosed:YES];
+  [debug_window[number] setIgnoresMouseEvents:YES];
+  [debug_window[number] setLevel:NSFloatingWindowLevel];
 
-  [debug_window orderFront:nil];
+  [debug_window[number] orderFront:nil];
 }
 
 gboolean
@@ -1137,11 +1165,11 @@ show_window_internal (GdkWindow *window,
   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
     _gdk_quartz_window_attach_to_parent (window);
 
-  /* Create a crossing event for managed windows that pop up under the
-   * mouse. Part of the workarounds for problems with the tracking rect API.
+  /* Create a crossing event for windows that pop up under the mouse. Part
+   * of the workarounds for problems with the tracking rect API.
    */
-  if (impl->toplevel && private->window_type != GDK_WINDOW_TEMP)
-    _gdk_quartz_events_trigger_crossing_events ();
+  if (impl->toplevel)
+    _gdk_quartz_events_trigger_crossing_events (TRUE);
 
   GDK_QUARTZ_RELEASE_POOL;
 }